package com.blacktea.magicapi.policy.magicapiuiuser;

import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.IdUtil;
import com.blacktea.magicapi.base.BaseConstant;
import com.blacktea.magicapi.entites.domain.MguMagicUiUser;
import com.blacktea.magicapi.entites.dto.UiUserDto;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: black tea
 * @date: 2022/1/1 23:22
 */
public class UiUserMapPolicy implements UiUserPolicy{

    private static Map<String, UiUserDto> MAGIC_USER_MAP = new ConcurrentHashMap<>();
    private static Map<String, String> BLACKLIST_IP_MAP = new ConcurrentHashMap<>();
    private static Map<String, String> WHITELIST_IP_MAP = new ConcurrentHashMap<>();

    @Override
    public UiUserDto getUser(String token) {
        return MAGIC_USER_MAP.get(token);
    }

    @Override
    public synchronized String buildToken(UiUserDto uiUser) {
        // 登录成功,随机生成一个token
        String token = IdUtil.simpleUUID();
        MAGIC_USER_MAP.put(token,uiUser);
        return token;
    }

    @Override
    public List<UiUserDto> users() {
        return new ArrayList<>(MAGIC_USER_MAP.values());
    }

    @Override
    public synchronized void removeByToken(String token) {
        MAGIC_USER_MAP.remove(token);
    }

    @Override
    public List<UiUserDto> getByUsername(String username) {
        return MAGIC_USER_MAP.values()
                .stream()
                .filter(u -> Validator.equal(u.getUser().getUsername(),username))
                .collect(Collectors.toList())
                ;
    }

    @Override
    public String getWhitelist(MguMagicUiUser user) {
        return WHITELIST_IP_MAP.get(user.getId());
    }

    @Override
    public void putWhitelist(MguMagicUiUser user, List<String> ips) {
        this.putIp(user,ips,WHITELIST_IP_MAP);
    }

    @Override
    public void removeByIpWhitelist(MguMagicUiUser user, List<String> matchIps) {
       this.removeIps(user,matchIps,WHITELIST_IP_MAP);
    }

    @Override
    public void removeAllWhitelist(MguMagicUiUser user) {
        WHITELIST_IP_MAP.remove(user.getId());
    }

    @Override
    public void replaceWhitelist(MguMagicUiUser user, Map<String, String> replaceIpMap) {
        WHITELIST_IP_MAP.put(user.getId(),this.replaceIps(user,replaceIpMap));
    }

    @Override
    public String getBlacklist(MguMagicUiUser user) {
        return BLACKLIST_IP_MAP.get(user.getId());
    }


    @Override
    public void putBlacklist(MguMagicUiUser user, List<String> ips) {
        this.putIp(user,ips,BLACKLIST_IP_MAP);
    }

    @Override
    public void removeByIpBlacklist(MguMagicUiUser user, List<String> matchIps) {
        this.removeIps(user,matchIps,BLACKLIST_IP_MAP);
    }

    @Override
    public void removeAllBlacklist(MguMagicUiUser user) {
        BLACKLIST_IP_MAP.remove(user.getId());
    }

    @Override
    public void replaceBlacklist(MguMagicUiUser user, Map<String, String> replaceIpMap) {
        BLACKLIST_IP_MAP.put(user.getId(),this.replaceIps(user,replaceIpMap));
    }

    private void putIp(MguMagicUiUser user, List<String> ips, Map<String, String> ipMap){
        StringJoiner ipJoiner = new StringJoiner(BaseConstant.Symbol.COMMA);
        ips.forEach(ipJoiner::add);
        Optional.ofNullable(this.getBlacklist(user)).ifPresent(ips::add);
        ipMap.put(user.getId(),ipJoiner.toString());
    }

    private void removeIps(MguMagicUiUser user, List<String> matchIps, Map<String,String> ipMap){
        Optional.ofNullable(this.getBlacklist(user)).ifPresent(ips -> {
            StringJoiner ipJoiner = new StringJoiner(BaseConstant.Symbol.COMMA);
            Arrays.stream(ips.split(BaseConstant.Symbol.COMMA)).forEach(ip -> {
                if (!matchIps.contains(ip)){
                    ipJoiner.add(ip);
                }
            });
            ipMap.put(user.getId(),ipJoiner.toString());
        });
    }

    private String replaceIps(MguMagicUiUser user, Map<String, String> replaceIpMap){
        String blacklist = this.getBlacklist(user);
        StringJoiner ipJoiner = new StringJoiner(",");
        if (Validator.isNull(blacklist)){
            replaceIpMap.values().forEach(ipJoiner::add);
        }else {
            Arrays.stream(blacklist.split(BaseConstant.Symbol.COMMA))
                    .forEach(ip -> ipJoiner.add(replaceIpMap.getOrDefault(ip,ip)));
        }
        return ipJoiner.toString();
    }

}
